const placeholder = "geo"
const Pat = {
	eq:/\=/,
	divid:/[\+\-\*\/](?![a-zA-Z\d\^\+\-\*\/]*?\))/g,
	oper:/[\+\-\*\/]/g,
	operStart:/^[\+\-\*\/]/,
	placeholder:/geo/,
	group:/^\(.*?\)$/,
	space:/\s+/g,
	//清除多余+号
	clean:/(\+)(?:\s*\1)/g,
	arg:/[x|y]/g,
	argx:/x/,
	argy:/y/,


	placeholder:/geo/,
	pow:/pow\((.*?),(.*?)\)/,
	log:/log\((.*?),(.*?)\)/,
	lg:/lg\((.*?)\)/,
	ln:/ln\((.*?)\)/,
	// pow1:/([a-zA-Z\d\.]+)\^([a-zA-Z\d\.]+)/,
	pow1:/(.*?)\^(.*)/,
	pow_nocache:/pow\((?:.*?),(?:.*?)\)/,
	// E:/^E$/,
	// PI:/^PI$/,
	mathCst:/^([a-zA-Z0-9]+?)$/,

	math:/([a-zA-Z]+[\d]?)\((.*?)\)/
}
const Arg = {
	x:"x",
	y:"y"
}
const MathPat = [
"pow",
"pow1",
"log",
"lg",
"ln",
// "E",
// "PI",
"mathCst"
]

export default class Func{
	static parseInput(text=""){
		text=text.replace(Pat.space,"")

		// let ttt=text.split(Pat.divid).filter(i=>i)
		// console.log(ttt)
		// return

		if(!text)return false
		let parts = text.split(Pat.eq)
		let res = null
		switch(parts.length){
			case 2:
				res = Func.parseEq(parts,text)
				break
			case 1:
				res = Func.parseFn(parts[0])
				break
			default:
				res = false
				break
		}
		if(res)
			res.raw = text
		return res
	}
	static parseEq(parts,text){
		let exprs = parts.map((ip)=>Func.parseExpr(ip))
		let expr = "return "+ `${exprs[0]}-(${exprs[1]})`
		let argx = text.match(Pat.argx)
		let argy = text.match(Pat.argy)
		let arg = null
		let fnExpr = null
		if(argx&&argy){
			arg="xy"
			fnExpr = new Function(Arg.x,Arg.y,expr).toString()
		}
		else {
			arg=(argx||argy||[Arg.x])[0]
			fnExpr = new Function(arg,expr).toString()
		}
		return {
			eq:true,
			arg,
			fnExpr
		}
	}
	static parseFn(part){
		let expr = "return "+ Func.parseExpr(part)
		let argx = part.match(Pat.argx)
		let argy = part.match(Pat.argy)
		let arg = (argx||argy||[Arg.x])[0]
		let fnExpr = new Function(arg,expr).toString()
		if(argx&&argy)return false
		return {
			arg,
			fnExpr
		}
	}
	static parseExpr(ip){
		let opers = []
		let items = []
		let returnStr = []
		let rawitems = []
		let isGroup = ip.match(Pat.group)
		let res = ""
		if(isGroup)
			ip = ip.substring(1,ip.length-1)
		if(!Pat.operStart.test(ip)){
			ip = "+"+ip
		}
		rawitems = ip.split(Pat.divid).filter(i=>i)
		opers = ip.match(Pat.divid)
		rawitems.forEach(ri=>{
			let f = "";
			if(ri.match(Pat.group))
				f = Func.parseExpr(ri)
			else 
				f=Func.parseFunction(ri)
			items.push(f)
		})

		items.forEach((item,i)=>{
			returnStr.push(opers[i])
			returnStr.push(item)
		})
		res = returnStr.join("").replace(Pat.clean,"$1")
		if(isGroup) return "("+res+")"
		return res
	}
	static parseFunction(ip){
		if(!ip)return ""
		let rs=MathPat.map((mp=>{
			let r = Func[mp](ip)
			if(r)r=`(${r})`
			return r
		})).filter(r=>r)
		if(rs.isEmpty()){
			rs = [Func.math(ip)]
		}
		return rs[0]||ip
	}
	static math(ip){
		let expr = false
		let r = ip.match(Pat.math)
		let cache = ""
		if(r){
			try{
				let a1 = r[1]
				let a2 = Func.parseExpr(r[2])
				console.log(a1,a2)
				expr = `Math.${a1}(${a2})`
				cache = r[0]
				//组合
				if(cache.length<ip.length){
					let nip = ip.replace(Pat.math,placeholder)
					let nexpr = Func.parseExpr(nip)
					if(nexpr)
						expr = nexpr.replace(Pat.placeholder,expr)
				}
			}catch(e){
				expr = false
			}
		}
		return expr
	}
	static pow(ip){
		let expr = false
		let r = ip.match(Pat.pow)
		let cache = ""
		if(r){
			let a1 = Func.parseExpr(r[1])
			let a2 = Func.parseExpr(r[2])
			console.log(a1,a2)
			expr = `Math.pow(${a1},${a2})`

			cache = r[0]
			//组合
			if(cache.length<ip.length){
				// let nip = ip.replace(Pat.pow_nocache,placeholder)
				let nip = ip.replace(Pat.pow,placeholder)
				let nexpr = Func.parseExpr(nip)
				if(nexpr)
					expr = nexpr.replace(Pat.placeholder,expr)
			}
		}
		return expr
	}
	static pow1(ip){
		let m = ip.match(Pat.pow1)
		if(m)
			return `Math.pow(${m[1]},${m[2]})`
		return false
	}
	static log(ip){
		//log(x)===e^y=x
		let expr = false
		let r = ip.match(Pat.log)
		let cache = ""
		if(r){
			let a1 = Func.parseExpr(r[1])
			let a2 = Func.parseExpr(r[2])
			console.log(a1,a2)
			expr = `Math.log(${a2})/Math.log(${a1})`

			cache = r[0]
			//组合
			if(cache.length<ip.length){
				let nip = ip.replace(Pat.log,placeholder)
				let nexpr = Func.parseExpr(nip)
				if(nexpr)
					expr = nexpr.replace(Pat.placeholder,expr)
			}
		}
		return expr
	}
	static lg(ip){
		//lg(x)=log(10,x)
		let expr = false
		let r = ip.match(Pat.lg)
		let cache = ""
		if(r){
			let a1 = Func.parseExpr(r[1])
			console.log(a1)
			expr = `Math.log(${a1})/Math.LN10`

			cache = r[0]
			//组合
			if(cache.length<ip.length){
				let nip = ip.replace(Pat.lg,placeholder)
				let nexpr = Func.parseExpr(nip)
				if(nexpr)
					expr = nexpr.replace(Pat.placeholder,expr)
			}
		}
		return expr
	}
	static ln(ip){
		//ln(x)=log(10,x)
		let expr = false
		let r = ip.match(Pat.ln)
		let cache = ""
		if(r){
			let a1 = Func.parseExpr(r[1])
			console.log(a1)
			expr = `Math.log(${a1})`

			cache = r[0]
			//组合
			if(cache.length<ip.length){
				let nip = ip.replace(Pat.ln,placeholder)
				let nexpr = Func.parseExpr(nip)
				if(nexpr)
					expr = nexpr.replace(Pat.placeholder,expr)
			}
		}
		return expr
	}
	static mathCst(ip){
		let expr = false
		let r = ip.match(Pat.mathCst)
		let cache = ""
		if(r){
			let c = r[0]
			expr = Math[c]?`Math.${c}`:false
		}
		return expr
	}
	// static E(ip){
	// 	let expr = false
	// 	let r = ip.match(Pat.E)
	// 	let cache = ""
	// 	if(r){
	// 		return "Math.E"
	// 	}
	// 	return expr
	// }
	// static PI(ip){
	// 	let expr = false
	// 	let r = ip.match(Pat.PI)
	// 	let cache = ""
	// 	if(r){
	// 		return "Math.PI"
	// 	}
	// 	return expr
	// }
}